package com.enation.app.javashop.manager.api.trade;

import com.enation.app.javashop.core.aftersale.AftersaleErrorCode;
import com.enation.app.javashop.core.client.member.MemberHistoryReceiptClient;
import com.enation.app.javashop.core.excel.ExcelManager;
import com.enation.app.javashop.core.shop.model.vo.ShopLogisticsSettingVO;
import com.enation.app.javashop.core.shop.service.ShopLogisticsCompanyManager;
import com.enation.app.javashop.core.statistics.util.DateUtil;
import com.enation.app.javashop.core.trade.cart.model.dos.OrderPermission;
import com.enation.app.javashop.core.trade.order.model.dos.OrderItemsDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderLogDO;
import com.enation.app.javashop.core.trade.order.model.dto.OrderQueryParam;
import com.enation.app.javashop.core.trade.order.model.enums.ShipTypeEnum;
import com.enation.app.javashop.core.trade.order.model.vo.*;
import com.enation.app.javashop.core.trade.order.service.OrderLogManager;
import com.enation.app.javashop.core.trade.order.service.OrderOperateManager;
import com.enation.app.javashop.core.trade.order.service.OrderQueryManager;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.framework.context.AdminUserContext;
import com.enation.app.javashop.framework.database.Page;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.security.model.Admin;
import com.enation.app.javashop.framework.util.BeanUtil;
import com.enation.app.javashop.framework.util.JsonUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

/**
 * 平台订单API
 *
 * @author Snow create in 2018/6/13
 * @version v2.0
 * @since v7.0.0
 */
@Api(description = "平台订单API")
@RestController
@RequestMapping("/admin/trade/orders")
@Validated
public class OrderManagerController {

    @Autowired
    private OrderQueryManager orderQueryManager;

    @Autowired
    private OrderOperateManager orderOperateManager;

    @Autowired
    private OrderLogManager orderLogManager;

    @Autowired
    private MemberHistoryReceiptClient memberHistoryReceiptClient;

    @Autowired
    private ExcelManager excelManager;

    @Autowired
    private ShopLogisticsCompanyManager shopLogisticsCompanyManager;

    protected final Log logger = LogFactory.getLog(this.getClass());

    @ApiOperation(value = "查询订单列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "ship_name", value = "收货人", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "goods_name", value = "商品名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "buyer_name", value = "买家名字", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "ship_mobile", value = "收货人手机号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "nick_name", value = "会员名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "lv1_member_nick_name", value = "团长名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "lv1_member_mobile", value = "团长手机号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "start_time", value = "开始时间", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "end_time", value = "结束时间", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "seller_id", value = "店铺ID", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "order_status", value = "订单状态", dataType = "String", paramType = "query",
                    allowableValues = "ALL,WAIT_PAY,WAIT_SHIP,WAIT_ROG,CANCELLED,COMPLETE,WAIT_COMMENT,REFUND",
                    example = "ALL:所有订单,WAIT_PAY:待付款,WAIT_SHIP:待发货,WAIT_ROG:待收货," +
                            "CANCELLED:已取消,COMPLETE:已完成,WAIT_COMMENT:待评论,REFUND:售后中"),
            @ApiImplicitParam(name = "member_id", value = "会员ID", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "page_no", value = "页数", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "page_size", value = "条数", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "payment_type", value = "支付方式", dataType = "String", paramType = "query",
                    allowableValues = "ONLINE,COD", example = "ONLINE:在线支付,COD:货到付款"),
            @ApiImplicitParam(name = "order_type", value = "订单类型", dataType = "String", paramType = "query",
                    allowableValues = "normal,pintuan,shetuan", example = "normal:普通订单,pintuan:拼团订单,shetuan:社团订单"),
            @ApiImplicitParam(name = "client_type", value = "订单来源", dataType = "String", paramType = "query",
                    allowableValues = "PC,WAP,NATIVE,REACT,MINI", example = "PC:pc客户端,WAP:WAP客户端,NATIVE:原生APP,REACT:RNAPP,MINI:小程序")
    })
    @GetMapping()
    public Page list(@ApiIgnore String orderSn, @ApiIgnore String shipName, @ApiIgnore String goodsName, @ApiIgnore String buyerName,
                     @ApiIgnore String shipMobile, @ApiIgnore String nickName, @ApiIgnore String lv1MemberNickName, @ApiIgnore String lv1MemberMobile,
                     @ApiIgnore Long startTime, @ApiIgnore Long endTime, @ApiIgnore String orderStatus,
                     @ApiIgnore Integer pageNo, @ApiIgnore Integer pageSize, @ApiIgnore Integer memberId, @ApiIgnore Integer sellerId,
                     @ApiIgnore String paymentType, @ApiIgnore String orderType, @ApiIgnore String clientType) {

        OrderQueryParam param = new OrderQueryParam();
        param.setOrderSn(orderSn);
        //如果输入订单编号，忽略其它条件
        if (StringUtil.isEmpty(orderSn)) {
            param.setShipName(shipName);
            param.setGoodsName(goodsName);
            param.setBuyerName(buyerName);
            param.setOrderStatus(orderStatus);
            param.setStartTime(startTime);
            param.setEndTime(endTime);
            // 如果查询时没有指定默认时间区间，默认查询7天的订单
            if (ObjectUtils.isEmpty(startTime) && ObjectUtils.isEmpty(endTime)) {
                param.setStartTime(DateUtil.startOfWeekAgoDay());
            }
            param.setMemberId(memberId);
            param.setSellerId(sellerId);
            param.setPaymentType(paymentType);
            param.setClientType(clientType);
            param.setOrderType(orderType);
            param.setShipMobile(shipMobile);
            param.setNickName(nickName);
            param.setLv1MemberNickName(lv1MemberNickName);
            param.setLv1MemberMobile(lv1MemberMobile);
        }

        param.setPageNo(pageNo);
        param.setPageSize(pageSize);
        Page page = this.orderQueryManager.listDistributionOrder(param);
        return page;
    }


    @ApiOperation(value = "导出订单列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "ship_name", value = "收货人", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "goods_name", value = "商品名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "buyer_name", value = "买家名字", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "ship_mobile", value = "收货人手机号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "nick_name", value = "会员名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "lv1_menber_nick_name", value = "团长名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "lv1_menber_mobile", value = "团长手机号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "start_time", value = "开始时间", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "end_time", value = "结束时间", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "seller_id", value = "店铺ID", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "order_status", value = "订单状态", dataType = "String", paramType = "query",
                    allowableValues = "ALL,WAIT_PAY,WAIT_SHIP,WAIT_ROG,CANCELLED,COMPLETE,WAIT_COMMENT,REFUND",
                    example = "ALL:所有订单,WAIT_PAY:待付款,WAIT_SHIP:待发货,WAIT_ROG:待收货," +
                            "CANCELLED:已取消,COMPLETE:已完成,WAIT_COMMENT:待评论,REFUND:售后中"),
            @ApiImplicitParam(name = "member_id", value = "会员ID", dataType = "int", paramType = "query"),
    })
    @GetMapping("/export")
    public List export(@ApiIgnore String orderSn, @ApiIgnore String shipName, @ApiIgnore String goodsName, @ApiIgnore String buyerName,
                       @ApiIgnore String shipMobile, @ApiIgnore String nickName, @ApiIgnore String lv1MenberNickName, @ApiIgnore String lv1MenberMobile,
                       @ApiIgnore Long startTime, @ApiIgnore Long endTime, @ApiIgnore String orderStatus,
                       @ApiIgnore Integer memberId, @ApiIgnore Integer sellerId) {

        OrderQueryParam param = new OrderQueryParam();
        param.setOrderSn(orderSn);
        param.setShipName(shipName);
        param.setGoodsName(goodsName);
        param.setBuyerName(buyerName);
        param.setOrderStatus(orderStatus);
        param.setStartTime(startTime);
        param.setEndTime(endTime);
        param.setPageNo(1);
        param.setPageSize(1000);
        param.setMemberId(memberId);
        param.setSellerId(sellerId);
        param.setShipMobile(shipMobile);
        param.setNickName(nickName);
        param.setLv1MemberNickName(lv1MenberNickName);
        param.setLv1MemberMobile(lv1MenberMobile);

        Page page = this.orderQueryManager.listDistributionOrder(param);
        return page.getData();
    }


    @ApiOperation(value = "查询单个订单明细")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")
    })
    @GetMapping(value = "/{order_sn}")
    public OrderDetailVO get(@ApiIgnore @PathVariable("order_sn") String orderSn) {
        OrderDetailVO detailVO = this.orderQueryManager.getModel(orderSn, null);
        if (detailVO.getNeedReceipt().intValue() == 1) {
            detailVO.setReceiptHistory(memberHistoryReceiptClient.getReceiptHistory(orderSn));
        }

        return detailVO;
    }

    @ApiOperation(value = "查询单个订单物流信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")
    })
    @GetMapping(value = "/ship_detail/{order_sn}")
    public List<OrderItemsVO> shipDetail(@ApiIgnore @PathVariable("order_sn") String orderSn) {

        // 1.验证订单有效性
        OrderDetailDTO orderDetail = this.orderQueryManager.getModel(orderSn);
        if (ObjectUtils.isEmpty(orderDetail)) {
            throw new ServiceException(AftersaleErrorCode.E604.name(), AftersaleErrorCode.E604.describe());
        }

        // 2.获取订单对应的订单详情和skuList（skuList中有商品的售后状态，订单详情中没有）
        List<OrderItemsDO> orderItems = this.orderQueryManager.getOrderItems(orderSn);
        List<OrderSkuVO> skuList = JsonUtil.jsonToList(orderDetail.getItemsJson(),OrderSkuVO.class);
        if (CollectionUtils.isEmpty(skuList)) {
            throw new ServiceException(AftersaleErrorCode.E602.name(), AftersaleErrorCode.E602.describe());
        }

        // 3.将商品的售后状态一起返回，商品已申请售后不允许分包裹发货
        List<OrderItemsVO> orderItemsVOList = new ArrayList<>();
        for (OrderSkuVO orderSkuVO : skuList) {
            String serviceStatus = orderSkuVO.getServiceStatus();
            for (OrderItemsDO orderItemDO : orderItems) {
                // skuid相同再进行赋值
                if (orderItemDO.getProductId().equals(orderSkuVO.getSkuId())) {
                    OrderItemsVO orderItemsVO = new OrderItemsVO();
                    BeanUtil.copyProperties(orderItemDO, orderItemsVO);
                    orderItemsVO.setServiceStatus(serviceStatus);
                    orderItemsVOList.add(orderItemsVO);
                }
            }
        }
        return orderItemsVOList;
    }

    @ApiOperation(value = "订单按商品分包裹发货", notes = "商家对某订单执行按商品分包裹发货操作")
    @ResponseBody
    @PostMapping(value = "/split/delivery")
    public String splitPackageShip(@Valid @RequestBody DeliveryVO deliveryVO) {
        try {
            deliveryVO.setShipType(ShipTypeEnum.GLOBAL.name());
            if(StringUtils.isEmpty(deliveryVO.getDeliveryNo())){
                deliveryVO.setLogiId(0);
                deliveryVO.setLogiName("自提配送");
                deliveryVO.setDeliveryNo("00000");
                deliveryVO.setShipType(ShipTypeEnum.SELF.name());
            }
            String operator = "管理员";
            Admin admin = AdminUserContext.getAdmin();
            if (!ObjectUtils.isEmpty(admin)) {
                operator = admin.getUsername();
            }
            deliveryVO.setOperator("平台:" + operator);
            orderOperateManager.partShip(deliveryVO, OrderPermission.admin);
            return "SUCCESS";
        } catch (Exception e) {
            logger.error("分包裹发货失败", e);
            return "FAIL";
        }
    }

    @ApiOperation(value = "确认收款")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path"),
            @ApiImplicitParam(name = "pay_price", value = "付款金额", dataType = "double", paramType = "query")
    })
    @PostMapping(value = "/{order_sn}/pay")
    public String payOrder(@ApiIgnore @PathVariable("order_sn") String orderSn, @ApiIgnore Double payPrice) {
        this.orderOperateManager.payOrder(orderSn, payPrice, "", OrderPermission.admin);
        return "";
    }


    @ApiOperation(value = "取消订单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path"),
    })
    @PostMapping(value = "/{order_sn}/cancelled")
    public String cancelledOrder(@ApiIgnore @PathVariable("order_sn") String orderSn) {

        CancelVO cancelVO = new CancelVO();
        cancelVO.setReason("管理员取消");
        cancelVO.setOrderSn(orderSn);
        cancelVO.setOperator("平台管理员");

        this.orderOperateManager.cancel(cancelVO, OrderPermission.admin);
        return "";
    }


    @ApiOperation(value = "查询订单日志")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "order_sn", value = "订单编号", required = true, dataType = "String", paramType = "path")
    })
    @GetMapping(value = "/{order_sn}/log")
    public List<OrderLogDO> getList(@ApiIgnore @PathVariable("order_sn") String orderSn) {
        List<OrderLogDO> logDOList = this.orderLogManager.listAll(orderSn);
        return logDOList;
    }

    @ApiOperation(value = "导入订单批量发货")
    @ApiImplicitParam(name = "uploadFile", value = "社团商品信息文件.xlsx", paramType = "form", dataType = "__File", required = true)
    @PostMapping(value = "/shipOrderImport", headers = "content-type=multipart/form-data")
    public void shipOrderImport(@RequestParam("uploadFile") MultipartFile uploadFile) {
        excelManager.shipOrderImport(uploadFile);
    }

    @ApiOperation(value = "平台查询物流公司列表", response = ShopLogisticsSettingVO.class)
    @GetMapping(value = "/express/list/{seller_id}")
    public List list(@ApiIgnore @PathVariable("seller_id") Integer sellerId) {
        return this.shopLogisticsCompanyManager.list(sellerId);
    }
}
